package org.zoomdev.zoom.dao.impl;

import org.zoomdev.zoom.aop.Constructor;
import org.zoomdev.zoom.aop.factory.ConstructorFactory;
import org.zoomdev.zoom.common.exceptions.ZoomException;
import org.zoomdev.zoom.dao.Dao;
import org.zoomdev.zoom.dao.Entity;
import org.zoomdev.zoom.dao.EntityField;
import org.zoomdev.zoom.dao.annotations.Join;
import org.zoomdev.zoom.dao.annotations.Link;
import org.zoomdev.zoom.dao.structs.JoinMeta;
import org.zoomdev.zoom.dao.structs.TableMeta;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedHashSet;
import java.util.Set;

public class BeanEntity extends Entity {

    private final Constructor constructor;


    private final Set<TableMeta> tables = new LinkedHashSet<>();


    private final JoinMeta[] joinMetas;

    private final Dao dao;
    private final Class<?> type;

    public BeanEntity(Class<?> type,
                      Dao dao,
                      TableMeta table,
                      EntityField[] primaryKeys,
                      EntityField[] entityFields) {
        super(dao.sqlDriver(), table, primaryKeys, entityFields);
        this.type = type;
        this.constructor = ConstructorFactory.FACTORY.create(type);
        if (this.constructor == null) {
            throw new ZoomException("找不到无参构造函数" + type);
        }
        this.dao = dao;

//        for (EntityField field : entityFields) {
//            tables.add(field.getColumn().getTableMeta());
//        }

        Link link = type.getAnnotation(Link.class);
        if (link != null) {
            Join[] joins = link.value();
            joinMetas = getJoinConfigs(joins);
        } else {
            joinMetas = null;
        }
    }


    private JoinMeta[] getJoinConfigs(Join[] joins) {
        if (joins == null) return null;
        JoinMeta[] joinMetas = new JoinMeta[joins.length];
        for (int i = 0; i < joins.length; ++i) {
            Join join = joins[i];
            //
            JoinMeta joinMeta = new JoinMeta();
            joinMeta.setOn(join.on());
            joinMeta.setTable(join.table());
            joinMeta.setType(join.type());

            joinMetas[i] = joinMeta;
        }
        return joinMetas;
    }


    public JoinMeta[] getJoinMetas() {
        return joinMetas;
    }


    public int getTableCount() {
        return tables.size();
    }


    public TableMeta getTableMeta() {
        return tableMeta;
    }


    public Object fromResultSet(ResultSet rs, EntityField[] entityFields) {
        return null;
//        try {
//            Object data = constructor.newInstance();
//            int index = 1;
//
//            ResultSetMetaData meta = rs.getMetaData();
//            int columnCount = meta.getColumnCount();
//            String[] labelNames = new String[columnCount + 1];
//            String[] tableNames = new String[columnCount + 1];
//            int[] types = new int[columnCount + 1];
//            for (int i = 1; i < labelNames.length; i++) {
//                tableNames[i] = meta.getTableName(i);
//                labelNames[i] = meta.getColumnLabel(i);
//                types[i] = meta.getColumnType(i);
//            }
//
//            if (entityFields == null) {
//
//
//            } else {
//                for (EntityField field : entityFields) {
//                    ResultSetAdapter resultSetAdapter = field.getResultSetAdapter();
//                    Object value = resultSetAdapter.getObject(rs, index++);
//                    field.set(data, value);
//                }
//            }
//            return data;
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
    }


    public int[] generateKeys() {
        return new int[0];
    }


    public void parseGenerateKeys(ResultSet rs) {


    }


    public void buildSelect(SimpleSelect select, SqlConfig config) {

    }


    public void buildDelete(SimpleSelect select, SqlConfig config) {

    }


    public void buildInsert(Object data, SimpleSelect select, SqlConfig config) {

    }


    public void buildUpdate(Object data, SimpleSelect select, SqlConfig config) {

    }


    public Object newInstance() {
        return constructor.newInstance();
    }


    public Entity addTable(String table) {
        return dao.entity(type, table);
    }


    public Object fromResultSet(ResultSet rs) throws SQLException {
        return null;
    }
}
